import { Plugin, TFile, Notice, Menu, debounce } from 'obsidian';
import { DocumentShareSettings, DEFAULT_SETTINGS, DocumentMapping } from './types';
import { DocumentShareSettingTab } from './settings';
import { UploadModal } from './upload-modal';
import { DocumentListModal } from './document-list-modal';
import { ApiClient } from './api-client';

interface PersistedData {
  settings?: DocumentShareSettings;
  documentMapping?: DocumentMapping;
  // 兼容旧版本：可能还有其它根级字段（旧的 settings）
  [key: string]: any;
}

export default class DocumentSharePlugin extends Plugin {
  settings: DocumentShareSettings;
  apiClient: ApiClient;
  documentMapping: DocumentMapping = {};
  private autoUpdateHandlers: Map<string, () => void> = new Map();
  private decorationUpdateInterval: number | null = null;

  /**
   * 生成 API Token 的简单哈希值（用于识别账号）
   */
  private getTokenHash(token: string): string {
    if (!token || token.length < 16) {
      return token;
    }
    return token.substring(0, 8) + '...' + token.substring(token.length - 8);
  }

  /**
   * 读取持久化数据（兼容旧结构）
   */
  private async getPersistedData(): Promise<PersistedData> {
    const raw = (await this.loadData()) || {};
    return raw as PersistedData;
  }

  /**
   * 保存持久化数据
   */
  private async setPersistedData(data: PersistedData): Promise<void> {
    await this.saveData(data);
  }

  async onload() {
    console.log('加载文档分享插件');

    await this.loadSettings();
    await this.loadDocumentMapping();

    this.apiClient = new ApiClient(this.settings);

    this.addSettingTab(new DocumentShareSettingTab(this.app, this));

    this.addRibbonIcon('list', '查看ObShare文档历史', () => {
      this.viewDocumentList();
    });

    // 初次加载时刷新一次装饰
    this.refreshFileDecorations();

    // 定期刷新（5 秒检查一次）
    this.decorationUpdateInterval = window.setInterval(() => {
      this.refreshFileDecorations();
    }, 5000);

    // 布局变化时刷新（包括文件树重新渲染）
    this.registerEvent(
      this.app.workspace.on('layout-change', () => {
        this.refreshFileDecorations();
      }),
    );

    this.registerFileWatcher();

    this.addCommand({
      id: 'share-current-document',
      name: '分享当前文档',
      checkCallback: (checking: boolean) => {
        const activeFile = this.app.workspace.getActiveFile();

        if (activeFile && activeFile.extension === 'md') {
          if (!checking) {
            this.shareDocument(activeFile);
          }
          return true;
        }

        return false;
      },
    });

    this.addCommand({
      id: 'view-shared-documents',
      name: '查看已分享的文档',
      callback: () => {
        this.viewDocumentList();
      },
    });

    // 文件右键菜单
    this.registerEvent(
      this.app.workspace.on('file-menu', (menu: Menu, file: TFile) => {
        if (file.extension === 'md') {
          menu.addItem((item) => {
            item
              .setTitle('分享到服务器')
              .setIcon('upload-cloud')
              .onClick(() => {
                this.shareDocument(file);
              });
          });
        }
      }),
    );

    // 编辑器右键菜单
    this.registerEvent(
      this.app.workspace.on('editor-menu', (menu: Menu) => {
        menu.addItem((item) => {
          item
            .setTitle('分享当前文档')
            .setIcon('upload-cloud')
            .onClick(() => {
              const activeFile = this.app.workspace.getActiveFile();
              if (activeFile && activeFile.extension === 'md') {
                this.shareDocument(activeFile);
              } else {
                new Notice('请先打开一个 Markdown 文件');
              }
            });
        });
      }),
    );
  }

  onunload() {
    console.log('卸载文档分享插件');

    if (this.decorationUpdateInterval !== null) {
      window.clearInterval(this.decorationUpdateInterval);
      this.decorationUpdateInterval = null;
    }

    this.removeAllFileDecorations();
  }

  /**
   * 加载设置（兼容旧版本结构）
   */
  async loadSettings() {
    const data = await this.getPersistedData();

    // 旧版本可能直接把设置字段放在根上（没有 data.settings）
    const { documentMapping, ...maybeSettings } = data;
    const settingsSource = data.settings ?? (maybeSettings as Partial<DocumentShareSettings>);

    this.settings = Object.assign({}, DEFAULT_SETTINGS, settingsSource || {});
  }

  /**
   * 保存设置，保留 documentMapping
   */
  async saveSettings() {
    const data = await this.getPersistedData();

    const mergedSettings = Object.assign({}, data.settings || {}, this.settings);

    const newData: PersistedData = {
      ...data,
      settings: mergedSettings,
    };

    await this.setPersistedData(newData);

    // 使用最新配置重新初始化 API 客户端
    this.apiClient = new ApiClient(this.settings);
  }

  /**
   * 加载文档映射
   */
  async loadDocumentMapping() {
    const data = await this.getPersistedData();
    this.documentMapping = data.documentMapping || {};
  }

  /**
   * 保存文档映射，保留设置
   */
  async saveDocumentMapping() {
    const data = await this.getPersistedData();

    // 如果还没有 settings 字段，说明是旧结构，把根级字段视为 settings
    if (!data.settings) {
      const { documentMapping, ...maybeSettings } = data;
      data.settings = maybeSettings as DocumentShareSettings;
    }

    const newData: PersistedData = {
      ...data,
      documentMapping: this.documentMapping,
    };

    await this.setPersistedData(newData);
  }

  /**
   * 注册文件监听（修改 / 重命名 / 删除）
   */
  registerFileWatcher() {
    this.registerEvent(
      this.app.vault.on('modify', (file: TFile) => {
        if (file.extension === 'md') {
          this.handleFileModify(file);
        }
      }),
    );

    this.registerEvent(
      this.app.vault.on('rename', (file: TFile, oldPath: string) => {
        if (file.extension === 'md' && this.documentMapping[oldPath]) {
          this.documentMapping[file.path] = this.documentMapping[oldPath];
          delete this.documentMapping[oldPath];
          this.saveDocumentMapping();
        }
      }),
    );

    this.registerEvent(
      this.app.vault.on('delete', (file: TFile) => {
        if (file.extension === 'md' && this.documentMapping[file.path]) {
          delete this.documentMapping[file.path];
          this.saveDocumentMapping();
        }
      }),
    );
  }

  /**
   * 处理文件修改（自动更新到服务器）
   */
  handleFileModify(file: TFile) {
    if (!this.settings.enableAutoUpdate) {
      return;
    }

    const uuid = this.getCurrentAccountDocument(file.path);
    if (!uuid) {
      return;
    }

    const existingHandler = this.autoUpdateHandlers.get(file.path);
    if (existingHandler && (existingHandler as any).cancel) {
      (existingHandler as any).cancel();
    }

    const debouncedUpdate = debounce(
      async () => {
        await this.autoUpdateDocument(file, uuid);
      },
      this.settings.autoUpdateDelay,
      true,
    );

    this.autoUpdateHandlers.set(file.path, debouncedUpdate);
    debouncedUpdate();
  }

  /**
   * 自动更新文档
   */
  async autoUpdateDocument(file: TFile, uuid: string) {
    try {
      const content = await this.app.vault.read(file);

      const normalizedPath = file.path.replace(/\\/g, '/');
      const response = await this.apiClient.updateDocument(uuid, {
        title: file.basename,
        content,
        path: normalizedPath,
      });

      if (!response.success) {
        console.error('自动更新失败:', response.error || response.message);
        new Notice(`自动更新失败: ${response.error || response.message}`);
      }
    } catch (error: any) {
      console.error('自动更新错误:', error);
      new Notice(`自动更新出错: ${error.message}`);
    } finally {
      this.autoUpdateHandlers.delete(file.path);
    }
  }

  /**
   * 记录文档映射（在上传/更新成功后调用）
   */
  async recordDocumentMapping(filePath: string, uuid: string, author?: string) {
    const tokenHash = this.getTokenHash(this.settings.apiToken);

    if (!this.documentMapping[filePath] || !Array.isArray(this.documentMapping[filePath])) {
      this.documentMapping[filePath] = [];
    }

    const existingIndex = this.documentMapping[filePath].findIndex(
      (record) => record.tokenHash === tokenHash,
    );

    const newRecord = {
      uuid,
      tokenHash,
      author,
      uploadedAt: new Date().toISOString(),
    };

    if (existingIndex >= 0) {
      this.documentMapping[filePath][existingIndex] = newRecord;
    } else {
      this.documentMapping[filePath].push(newRecord);
    }

    await this.saveDocumentMapping();
  }

  /**
   * 移除文档映射
   */
  async removeDocumentMapping(filePath: string, uuid?: string) {
    if (!this.documentMapping[filePath] || !Array.isArray(this.documentMapping[filePath])) {
      return;
    }

    if (uuid) {
      this.documentMapping[filePath] = this.documentMapping[filePath].filter(
        (record) => record.uuid !== uuid,
      );
    } else {
      const tokenHash = this.getTokenHash(this.settings.apiToken);
      this.documentMapping[filePath] = this.documentMapping[filePath].filter(
        (record) => record.tokenHash !== tokenHash,
      );
    }

    if (this.documentMapping[filePath].length === 0) {
      delete this.documentMapping[filePath];
    }

    await this.saveDocumentMapping();
  }

  /**
   * 获取当前账号的文档 UUID
   */
  getCurrentAccountDocument(filePath: string): string | null {
    const records = this.documentMapping[filePath];
    if (!records || !Array.isArray(records) || records.length === 0) {
      return null;
    }

    const tokenHash = this.getTokenHash(this.settings.apiToken);
    const record = records.find((r) => r.tokenHash === tokenHash);
    return record ? record.uuid : null;
  }

  /**
   * 获取文件的所有账号文档记录
   */
  getAllAccountDocuments(filePath: string) {
    const records = this.documentMapping[filePath];
    return records && Array.isArray(records) ? records : [];
  }

  /**
   * 分享文档（打开上传弹窗）
   */
  async shareDocument(file: TFile) {
    if (!this.settings.apiUrl || !this.settings.apiToken) {
      new Notice('请先在设置中配置 API 地址和 API Token');
      return;
    }

    try {
      const content = await this.app.vault.read(file);

      new UploadModal(
        this.app,
        this,
        file.path,
        file.basename,
        content,
      ).open();
    } catch (error: any) {
      new Notice(`读取文件失败: ${error.message}`);
      console.error('读取文件错误:', error);
    }
  }

  /**
   * 查看文档列表
   */
  viewDocumentList() {
    if (!this.settings.apiUrl || !this.settings.apiToken) {
      new Notice('请先在设置中配置 API 地址和 API Token');
      return;
    }

    new DocumentListModal(this.app, this.apiClient, this).open();
  }

  /**
   * 刷新文件树中的分享图标
   */
  refreshFileDecorations() {
    const fileExplorer = this.app.workspace.getLeavesOfType('file-explorer')[0];
    if (!fileExplorer) {
      return;
    }

    const fileItems = (fileExplorer.view as any).fileItems;
    if (!fileItems) {
      return;
    }

    Object.keys(fileItems).forEach((filePath) => {
      const fileItem = fileItems[filePath];
      if (!fileItem || !fileItem.el) {
        return;
      }

      const isUploaded = this.getCurrentAccountDocument(filePath) !== null;
      let decorationEl = fileItem.el.querySelector('.obshare-uploaded-indicator') as HTMLElement | null;

      if (isUploaded) {
        if (!decorationEl) {
          decorationEl = document.createElement('span');
          decorationEl.addClass('obshare-uploaded-indicator');
          decorationEl.setAttribute('aria-label', '已上传到 ObShare');

          const uniqueId = `obshare-gradient-${Math.random().toString(36).substr(2, 9)}`;
          const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
          svg.setAttribute('viewBox', '0 0 166 166');
          svg.setAttribute('width', '12');
          svg.setAttribute('height', '12');

          const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
          const gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');
          gradient.setAttribute('id', uniqueId);
          gradient.setAttribute('x1', '0%');
          gradient.setAttribute('y1', '0%');
          gradient.setAttribute('x2', '100%');
          gradient.setAttribute('y2', '100%');

          const stop1 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
          stop1.setAttribute('offset', '0%');
          stop1.setAttribute('style', 'stop-color:#6366f1;stop-opacity:1');

          const stop2 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
          stop2.setAttribute('offset', '100%');
          stop2.setAttribute('style', 'stop-color:#8b5cf6;stop-opacity:1');

          gradient.appendChild(stop1);
          gradient.appendChild(stop2);
          defs.appendChild(gradient);
          svg.appendChild(defs);

          const docPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
          docPath.setAttribute(
            'd',
            'M48 20C48 15.5817 51.5817 12 56 12H92L118 38V146C118 150.418 114.418 154 110 154H56C51.5817 154 48 150.418 48 146V20Z',
          );
          docPath.setAttribute('fill', `url(#${uniqueId})`);
          svg.appendChild(docPath);

          const foldPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
          foldPath.setAttribute('d', 'M92 12L118 38H100C95.5817 38 92 34.4183 92 30V12Z');
          foldPath.setAttribute('fill', `url(#${uniqueId})`);
          foldPath.setAttribute('opacity', '0.6');
          svg.appendChild(foldPath);

          const shareCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
          shareCircle.setAttribute('cx', '104');
          shareCircle.setAttribute('cy', '120');
          shareCircle.setAttribute('r', '18');
          shareCircle.setAttribute('fill', '#10b981');
          shareCircle.setAttribute('opacity', '0.95');
          svg.appendChild(shareCircle);

          const linkPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
          linkPath.setAttribute(
            'd',
            'M107 117L109.5 119.5M104.5 124.5L102 127C101.2 127.8 100 127.8 99.2 127C98.4 126.2 98.4 125 99.2 124.2L101.7 121.7M106.3 118.3L108.8 115.8C109.6 115 110.8 115 111.6 115.8C112.4 116.6 112.4 117.8 111.6 118.6L109.1 121.1',
          );
          linkPath.setAttribute('stroke', 'white');
          linkPath.setAttribute('stroke-width', '2');
          linkPath.setAttribute('stroke-linecap', 'round');
          linkPath.setAttribute('fill', 'none');
          svg.appendChild(linkPath);

          decorationEl.appendChild(svg);

          const titleEl = fileItem.el.querySelector('.nav-file-title-content');
          if (titleEl) {
            titleEl.appendChild(decorationEl);
          }
        }
      } else if (decorationEl) {
        decorationEl.remove();
      }
    });
  }

  /**
   * 移除所有文件装饰器
   */
  removeAllFileDecorations() {
    const indicators = document.querySelectorAll('.obshare-uploaded-indicator');
    indicators.forEach((indicator) => indicator.remove());
  }
}

